package com.vr.cloudpicture.manager.websocket.handler;

import cn.hutool.core.collection.CollUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.vr.cloudpicture.manager.websocket.model.PictureEditResponseMessage;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 图片编辑广播
 *
 * @author hzh
 * @date 2025/05/28
 */
public class PictureEditBroadcast {
    /**
     * 保存所有连接的会话，key:pictureId,value:要编辑图片的用户会话
     */
    private static final Map<Long, Set<WebSocketSession>> pictureSessions = new ConcurrentHashMap<>();

    public static void addSession(Long pictureId, WebSocketSession session) {
        // 不存在pictureId这个key，则创建一个set，否则啥都不做
        pictureSessions.putIfAbsent(pictureId, ConcurrentHashMap.newKeySet());
        // 添加会话
        pictureSessions.get(pictureId).add(session);
    }

    public static void removeSession(Long pictureId, WebSocketSession session) {
        // 获取pictureId对应的session集合
        Set<WebSocketSession> sessions = pictureSessions.get(pictureId);
        // 如果pictureId对应的session集合不为空，则删除session
        if (sessions != null) {
            sessions.remove(session);
            // 当移除的是最后一个session后，同时也移除这个pictureId
            if (sessions.isEmpty()) {
                pictureSessions.remove(pictureId);
            }
        }
    }

    /**
     * 广播到同一张图片的所有编辑者
     *
     * @param pictureId       图片id
     * @param responseMessage 响应消息
     * @param excludeSession  排除会话
     */
    public static void broadcastToPicture(Long pictureId, PictureEditResponseMessage responseMessage, WebSocketSession excludeSession) throws IOException {
        // 获取pictureId对应的会话集合
        Set<WebSocketSession> sessionSet = pictureSessions.get(pictureId);
        if (CollUtil.isNotEmpty(sessionSet)) {
            // 表示有人要编辑这个图片
            // 创建序列化器，将Long类型转化成String类型，避免精度丢失
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.registerModule(new JavaTimeModule());
            objectMapper.registerModule(
                    new SimpleModule()
                            .addSerializer(Long.class, ToStringSerializer.instance)
                            // 支持Long的基本类型
                            .addSerializer(Long.TYPE, ToStringSerializer.instance)
            );
            String message = objectMapper.writeValueAsString(responseMessage);
            TextMessage textMessage = new TextMessage(message);
            for (WebSocketSession session : sessionSet) {
                // 排除的session不发送
                if (session.equals(excludeSession)) {
                    continue;
                }
                // 会话是否在线
                if (session.isOpen()) {
                    // 发送消息
                    session.sendMessage(textMessage);
                }
            }
        }
    }

    /**
     * 全部广播
     */
    public static void broadcastToPicture(Long pictureId, PictureEditResponseMessage responseMessage) throws IOException {
        broadcastToPicture(pictureId, responseMessage, null);
    }
}
